package com.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.task.common.util.body.CommonModel;
import com.task.common.util.body.JsonResult;
import com.task.common.util.body.ModelTool;
import com.task.common.util.body.ResultTool;
import com.task.common.util.model.FieldUtil;
import com.task.entity.Chunk;
import com.task.entity.QingShuFile;
import com.task.mapper.ChunkMapper;
import com.task.mapper.FileMapper;
import com.task.service.IFileService;
import com.task.util.FileInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Huzz
 * @since 2021-10-11
 */
@Slf4j
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, QingShuFile> implements IFileService {

    @Value("${qingshu.resource.save-path}")
    private String diskFilePath;

    @Value("${qingshu.nginx.addr}")
    private String fileAddr;

    @Value("${qingshu.nginx.resource-path}")
    private String filePath;

    @Resource
    private FileMapper fileMapper;

    @Resource
    private ChunkMapper chunkMapper;

    /**
     * 文件大小: 2MB = 1024 * 1024 * 2
     */
    Long MAX_SIZE = 2097152L;

    @Override
    public JsonResult upload(MultipartFile musicFile) {
        if (musicFile.isEmpty()) {
            return ResultTool.fail("上传文件不能为空");
        }
        if (musicFile.getSize() > MAX_SIZE) {
            return ResultTool.fail("上传文件过大, 请使用大文件上传方式");
        }
        // 原文件名
        String fileName = musicFile.getOriginalFilename();
        // 后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        // 新文件名
        String newFileName = System.currentTimeMillis() + suffixName;
        // 开辟空间
        File dest = new File(diskFilePath + newFileName);
        // 若路径不存在,则创建路径
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            musicFile.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 文件信息保存到数据库
        QingShuFile file = new QingShuFile();
        file.setFileName(fileName);
        file.setPath(newFileName);
        file.setFileType(suffixName);
        file.setDel(0);
        // 创建信息
        FieldUtil.setCreatedField(file);
        if (fileMapper.insert(file) > 0) {
            // 上传成功, 返回文件信息
            return ResultTool.success(file);
        }

        return ResultTool.fail("上传失败");
    }

    @Override
    public CommonModel mergeFile(QingShuFile sysFile) {

        int code = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;

        //进行文件的合并操作
        // 转换为保存的文件名称形式
        String asHex = DigestUtils.md5DigestAsHex(sysFile.getFileName().getBytes(StandardCharsets.UTF_8));
        String suffix = sysFile.getFileName().substring(sysFile.getFileName().lastIndexOf("."));

        String file = diskFilePath + File.separator + sysFile.getIdentifier() + File.separator + asHex + suffix;
        String path = "/" + sysFile.getIdentifier()+ "/" + asHex + suffix;
        String folder = diskFilePath + File.separator + sysFile.getIdentifier();
        Integer fileSuccess = FileInfoUtils.merge(file, folder, asHex + suffix);
        // 清除分片记录
        sysFile.setPath(path);
        QueryWrapper<Chunk> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Chunk::getIdentifier, sysFile.getIdentifier())
                .eq(Chunk::getFilename, asHex + suffix);
        chunkMapper.delete(wrapper);
        //文件合并成功后，保存记录
        if (fileSuccess == HttpServletResponse.SC_OK) {
            fileMapper.insert(sysFile);
            code = HttpServletResponse.SC_OK;
        }
        //如果已经存在，则判断是否是同一个项目，同一个项目不用新增记录，否则新增
        else if (fileSuccess == HttpServletResponse.SC_MULTIPLE_CHOICES) {
            // 同一个项目
            QueryWrapper<QingShuFile> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda()
                    .eq(QingShuFile::getIdentifier, sysFile.getIdentifier())
                    .eq(QingShuFile::getFileName, sysFile.getFileName());
            List<QingShuFile> tfList = fileMapper.selectList(wrapper1);
            if (tfList.size() == 0) {
                fileMapper.insert(sysFile);
                code = HttpServletResponse.SC_MULTIPLE_CHOICES;
            } else {
                for (QingShuFile info : tfList) {
                    if (info.getRefProjectId().equals(sysFile.getRefProjectId())) {
                        QueryWrapper<QingShuFile> wrapper2 = new QueryWrapper<>();
                        wrapper2.lambda().eq(QingShuFile::getId, info.getId());
                        fileMapper.delete(wrapper2);
                        fileMapper.insert(sysFile);
                        code = HttpServletResponse.SC_MULTIPLE_CHOICES;
                    }
                }
            }
        } else {
            code = HttpServletResponse.SC_BAD_REQUEST;
        }

        return ModelTool.createModel().response(code, sysFile);
    }

    @Override
    public Page<QingShuFile> selectFileList(QingShuFile sysFile, Integer pageNum, Integer pageSize) {
        return fileMapper.selectPage(new Page<>(pageNum, pageSize), null);
    }

    @Override
    public boolean deleteFile(QingShuFile sysFile) {
        return fileMapper.deleteById(sysFile.getId()) > 0;
    }

    @Override
    public String getFilePath(Integer fileId) {
        QingShuFile file = baseMapper.selectById(fileId);

        return file != null ? "http://" + fileAddr + filePath + file.getPath() : "";
    }
}
